﻿#ifndef switch_h__
#define switch_h__

/*
 * 定义内部线程通讯
 */
#define TASK_DATA_MAX_SIZE 1024 //线程通信的最大数据长度
#define TASK_TTL_MAX        32  //最多进行32次交换

// 线程名定义
#define NAME_SWITCH     "SW  \0" //交换线程，注意用空格补齐4字节
#define NAME_MAIN       "MAIN\0" //主线程，注意用空格补齐4字节
#define NAME_HTTP       "HTTP\0" //HTTP线程，注意用空格补齐4字节
#define NAME_TCP        "TCP \0" //TCP通讯线程，注意用空格补齐4字节
#define NAME_LOG        "LOG \0" //日志线程，注意用空格补齐4字节

// 线程地址定义
typedef enum task_addr
{
    ADDR_IN,
    ADDR_OUT,
    ADDR_ALL,
    
    ADDR_SWITCH,
    ADDR_MAIN,
    ADDR_HTTP,
    ADDR_TCP,
    ADDR_LOG
}task_addr_t;

#define TASK_ADDR_TO_STRING(addr) (\
    (addr == ADDR_IN)? "IN  ": \
    (addr == ADDR_OUT)? "OUT ": \
    (addr == ADDR_ALL)? "ALL ":\
    (addr == ADDR_SWITCH)? "SW  ": \
    (addr == ADDR_MAIN)? "MAIN": \
    (addr == ADDR_HTTP)? "HTTP": \
    (addr == ADDR_TCP)? "TCP ":\
    (addr == ADDR_LOG)? "LOG ":\
    "ADDR_UNKNOWN")


//任务方向
typedef enum task_dir
{
    DIR_REQUEST,                   // 请求
    DIR_RESPONSE,                  // 回复
    DIR_NO_RESPONSE                // 不要求回复的请求
}task_dir_t;

//任务类型
typedef enum task_type
{
    TYP_PROG_QUIT,                          // 程序退出

    TYP_THRD_REGISTER,                      // 线程注册
    TYP_THRD_STOP,                          // 线程退出

    TYP_SERV_START,                         // 启动管理服务器
    TYP_SERV_NEW_CLIENT,                    // 有新的客户端
    TYP_SERV_DEL_CLIENT,                    // 客户端断开连接

    TYP_LOG_GET,                            // 将日志发送给远端
    TYP_LOG_ENTRY,                          // 一条日志
    TYP_LOG_LEVEL,                          // 日志等级
}task_type_t;

#define TASK_TYPE_TO_STRING(cmd) (\
    (cmd == TYP_PROG_QUIT)? "TYP_PROG_QUIT": \
    (cmd == TYP_THRD_REGISTER)? "TYP_THRD_REGISTER": \
    (cmd == TYP_THRD_STOP)? "TYP_THRD_STOP":\
    (cmd == TYP_SERV_START)? "TYP_SERV_START": \
    (cmd == TYP_SERV_NEW_CLIENT)? "TYP_SERV_NEW_CLIENT": \
    (cmd == TYP_SERV_DEL_CLIENT)? "TYP_SERV_DEL_CLIENT": \
    (cmd == TYP_LOG_GET)? "TYP_LOG_GET":\
    (cmd == TYP_LOG_ENTRY)? "TYP_LOG_ENTRY":\
    "CTL_CMD_UNKNOWN")

//任务携带的数据
typedef struct serv_data
{
    int port;       // 端口
}serv_data_t;

// TYP_LOG_SEND_TO_REMOTE携带的数据
typedef struct log_data
{
    unsigned long ip;
    unsigned int port;
    unsigned int data_size;                                              // 携带的数据长度
    unsigned char  data_buf[TASK_DATA_MAX_SIZE - 12];    // 数据区
}log_data_t;

typedef unsigned int task_session_t;

// 线程之间通信的任务结构
typedef struct thrd_comm_entry
{
    task_addr_t dst;                                // 目的线程
    task_addr_t src;                                // 源线程
    task_session_t session;                            // 会话ID，可以用于表示一个会话
    task_type_t type;                                // 任务类型
    task_dir_t dir;                                  // 任务方向
    unsigned int seqno;                              // 序列号，回复的序列号必须和请求的序列号相同
    unsigned int ttl;                                // 存活周期
    unsigned int data_size;                          // 携带的数据长度
    unsigned char  data_buf[TASK_DATA_MAX_SIZE];     // 数据区
}thrd_comm_entry_t;

// 线程通讯队列
typedef struct thrd_comm_queue
{
    std::queue<thrd_comm_entry_t> _queue;//队列
    boost::mutex _mutex;//队列互斥量
    boost::condition_variable _cond;//条件变量
}thrd_comm_queue_t;

// 线程接受的命令
typedef struct thrd_ctl_list_node
{
    task_type_t cmd;
    struct thrd_ctl_list_node * next;
}thrd_ctl_list_node_t;

int register_thrd(const char *name, thrd_comm_queue_t *_in_queue, thrd_comm_queue_t *_out_queue, boost::condition_variable *cond);
int register_thrd_ctl_cmd(const char *name, thrd_ctl_list_node_t * pnode);
int switch_start();
void switch_stop();

int send_task(
              unsigned int dst,                       // 目的线程
              unsigned int src,                       // 源线程
              unsigned int session,                   // 会话ID，可以用于表示一个会话
              task_type_t type,                       // 任务类型
              task_dir_t dir,                         // 任务方向
              unsigned int seqno,                     // 序列号，回复的序列号必须和请求的序列号相同
              unsigned int data_size,                 // 携带的数据长度
              unsigned char*  data_buf                 // 数据区
              );
int send_task_entry(thrd_comm_entry_t *ptask);

#endif // switch_h__